#include "app.h"
/*
        Parâmetro obrigatório: t (diz se é transmissor) ou r (diz se é receptor), path to file to be sent in transmitter's case
        Parâmetros opcionais a aceitar p/configurar a LinkLayer:
        - porta (/dev/ttyS0 (default), /dev/ttyS1)
        - baud rates (ainda nao descobri como incluir isto no programa)
                - B50,B75,B110,B134,B150,B200,B300,B600,B1200,B1800,B2400,B4800,B9600,B19200,B38400 (default),B57600,B115200,B230400
        - timeout (segundos) - 3s default
        - number of transmissions (3 default)
        - tamanho mámo da frame (bytes) - 128 default
        
        verificar parâmetros 
        se receptor:
                - llopen, handle errors
                - enquanto nãtiver tudo, le pacotes (tramas de informaç)
                - quando tiver tudo (aka recebe DISC) responde ao pedido de disconnect, diz q acabou e fecha
        se transmissor:
                - llopen, handle errors
                - verificar se ficheiro éádo e temos acesso a ele (se open sucede)
                - descobrir tamanho de ficheiro
                - enquanto nao se leu ficheiro todo faz-se read desde o sío em que estamos atéax size 
                (ou se nao tiver que chegue, do sío onde estamos ate file end), metemos num buffer e chamamos llwrite nele
                - llwrite supostamente trata de receber os RRs e REJs
                - quando tiver acabado manda DISC, recebe DISC, manda UA e manda-se abaixo
*/

int valid_frame_counter = 0;
int main(int argc, char** argv){
	char * bufz;
	int sizez;
	if ((argc < 3) || 
	(((strcmp("/dev/ttyS0", argv[1])!=0) && (strcmp("/dev/ttyS1", argv[1])!=0) &&(tolower(argv[2][0]) != 't' && tolower(argv[2][0]) != 'r')) 
	&& ((strcmp("/dev/ttyS0", argv[2])!=0) && (strcmp("/dev/ttyS1", argv[2])!=0) && (tolower(argv[1][0]) != 't' && tolower(argv[1][0]) != 'r')))) {
      printf("Usage:\t[t/r] nserial SerialPort\n\tex: nserial /dev/ttyS1\n");
      exit(-1);
    }    
   
   LinkLayer lin;
   ApplicationLayer appLayer;
   appLayer.status=0;
   appLayer.fileDescriptor=0;
   char* port = argv[1];
   strcpy(&lin.port[0],port);
   lin.sequenceNumber = 0;
   lin.timeout=3; //tempo q espera ate retransmissao
   lin.numRetransmissions=3; //nº tries em caso de falha
   lin.maxSize=512; //tamanho maximo da trama de informacao
   configureLinkLayer(&lin);
	FILE * f;
	unsigned int bytes_read = 0;
	FileStuff fileStuff; 
	FileReader reader;
   
   char * dataFrame;
	//escolha reciever/transmitter
	if(argv[1][0] == 't' || argv[2][0] == 't')
		appLayer.status = TRANS;
    else if(argv[1][0] == 'r' || argv[2][0] == 'r')
	    appLayer.status = RECIE;        
    //-----------------------------------------------------------------------------------------------------
    
    //se transmitter, tem de ter um param com path
    //validar
   if(appLayer.status == TRANS){
	   size_t valid_filepath = 0, input_size = 128;
		fileStuff.filename = malloc(input_size*sizeof(char));
		while(valid_filepath == 0){
		 	printf("Please specify a file path for the file to be sent;\n");
			bytes_read = getline(&fileStuff.filename,&input_size,stdin);

			//if it doesnt find \0, puts it
			if(fileStuff.filename[bytes_read-1] == '\n')
				fileStuff.filename[bytes_read-1] = '\0';
			
			initializeAndOpen(&reader, fileStuff.filename, lin.maxSize);
			if(!reader.file) {
				printf("File not found...\n");
				valid_filepath = 0;
			}else{valid_filepath = 1;}
		}
	}
        
	appLayer.fileDescriptor = llopen(lin.port, appLayer.status);
	if(appLayer.fileDescriptor <0){
     	return -1;
	}
    
   // TODO REMOVE
   lin.sequenceNumber = 0;
	if(appLayer.status == RECIE){ 
	   int firstPack = 1;    
		dataFrame = malloc((lin.maxSize*2+6)*sizeof(char)); //maxSize->tamanho da trama(stuffed)*2(pior caso)+6 posiçoes
		int find = 1;
		while(find != -1) {
			find = receiverMain(appLayer.fileDescriptor, dataFrame, lin.sequenceNumber);
      	if(find > 0){
   			llread(appLayer.fileDescriptor, dataFrame, find);  //find -> tamanho dados 			
   			if(firstPack==1){
   				/*tratar o primeiro pack = [F|A|C|BCC|..filename..| SEP | file_size |BCC2|F]*/
   				int valid = readFirstDataFrame(dataFrame, find, &fileStuff);
   				if(valid){
					f = fopen(fileStuff.filename, "wb");
   					if(!f) {
   						perror("fopen");
   						return -1;	
   					}
   					printf("Valid First Frame\n");
   					firstPack = 0;  
   					llclose(appLayer.fileDescriptor);
   					exit(0);
   				}else{
   					printf("First pack is invalid\n");
   				}   				
   			}else {printf("Regular packets\n");}
				fwrite(bufz, sizeof(char), sizez, f); 
   				++valid_frame_counter;
   				printf("valid_frame_counter: %d\n", valid_frame_counter);				
			}
		}
		if(find < 0){
			handleReceiverDisconnect(appLayer.fileDescriptor);
			return 0;
		} //DISCONNECT
		return 0;
	}else if (appLayer.status == TRANS){
		unsigned int sentFirstPacket = 0, currSize = 0;
		char * str_size; int countPack = 0;
		while(!reader.at_end){
			countPack++;
			printf("count = %d\n", countPack);
			if(sentFirstPacket == 0){
				printf("Preparing first info packet.............\n");
				 	
				//conversao size
				str_size = int_to_array(reader.file_size);//size always 4
				 	
				//conteudo: file_name + 'SEP' + file_size
				unsigned int packetSize = bytes_read + 5;
				unsigned int b;
				 	
				char * firstPacket = malloc(packetSize * sizeof(char));
			  	//copiar nome p/packet
				for(b = 0; b < bytes_read-1; b++)
					firstPacket[b]=fileStuff.filename[b];
				firstPacket[b++]=SEP;
				currSize = b;
				 	
				printf("converted int: ");
				//copiar size p/packet
				int z = 0;
				for(; b<(currSize + 4); b++, z++){
					printf("%x|",str_size[z]);
					firstPacket[b]=str_size[z];
				}
				printf("\n");
		
				unsigned int x;
				for(x = 0; x < packetSize; x++){
					printf("%x|",firstPacket[x]);
				}
				printf("\n");
				printf("name=%s|size=%d\n",fileStuff.filename,reader.file_size);
					
				llwrite(appLayer.fileDescriptor, firstPacket, packetSize);
				sentFirstPacket=1;
			}else{
				printf("Sending normal packet...............\n");
				int read = readBlock(&reader);
				llwrite(appLayer.fileDescriptor, reader.buffer, read);
			}
       }
       //close file
       closeReader(&reader);
  		 //send disconnect
  		 dataFrame=malloc(sizeof(char));
       llwrite(appLayer.fileDescriptor, dataFrame, 0);//send disconnect length = 0
       return 0;
    }else{    
      llclose(appLayer.fileDescriptor);
      return -1;
    }
 }
